package com.flute.icrawler.framework.autoadjust;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.flute.icrawler.config.CrawlConfigUtil;
import com.flute.tools.timer.IntervalExecutor;

/**
 * 网页抓取间隔自动调整器 由于大部分的网站对于访问间隔有限制，所以有必要对抓取的速度有一个总体的控制 通过对现有的抓取结果的分析，来计算出最佳的抓取间隔
 * 
 * 
 */
public class FetchAdjuster implements IAdjuster {
	private Logger logger = Logger.getLogger(FetchAdjuster.class);
	private AbleTimer timer;
	private IntervalExecutor executor;

	public enum FetchStatus {
		Success, Invalid, Reject, TimeOut, UnknowHostException
	};

	private Map<FetchStatus, Integer> mpStatusToCount = new HashMap<FetchStatus, Integer>();
	private List<AdjustTask> adjustTasks = new ArrayList<AdjustTask>();

	public FetchAdjuster(AbleTimer timer) {
		this.timer = timer;

		this.executor = getTimerRecord();
		executor.setName("Url Interval Logger");
		executor.setInterval(CrawlConfigUtil.getBaseConfig()
				.getFrameworkPrintInterval() * 1000);
		executor.start();
	}

	public void setFinished(boolean isFinished) {

		for (int i = 0; i < adjustTasks.size(); i++) {
			adjustTasks.get(i).setFinish(isFinished);
		}

		this.timer.setFinished(isFinished);
	}

	@Override
	public void setInterval(int ms) {
		timer.setInterval(ms);
	}

	public int getInterval() {
		return timer.getInterval();
	}

	public void addAdjusterStrategy(IAdjusterStrategy adjusterStrategy) {
		AdjustTask adjustTask = new AdjustTask(adjusterStrategy);
		adjustTask.setInterval(200000);
		adjustTask.setName(adjusterStrategy.getClass().getName());
		adjustTask.setDaemMode(true);
		// adjustTask.start();
		this.adjustTasks.add(adjustTask);
	}

	/**
	 * 获取该类处理结果的个数
	 * 
	 * @param fetchStatus
	 * @return
	 */
	public int getFetchStatusCount(FetchStatus fetchStatus) {
		if (null != mpStatusToCount.get(fetchStatus)) {
			return mpStatusToCount.get(fetchStatus);
		}
		return 0;
	}

	/**
	 * 将所有的调整策略任务进行调度
	 */
	@Override
	public void run() {
		for (int i = 0; i < adjustTasks.size(); i++) {
			adjustTasks.get(i).start();
		}

	}

	public AbleTimer getTimer() {
		return timer;
	}

	/**
	 * 记录爬虫运行时的注册状态 爬虫每爬一个URL就会将运行结果成功与否记录到此处
	 * 
	 * @param status
	 */
	public void recordFetchStatus(FetchStatus status) {
		count(status);
	}

	/**
	 * 将所有计数器清零
	 */
	public void clearFetchStatusCount() {

		if (null == mpStatusToCount) {
			return;
		}
		Iterator<FetchStatus> iterator = mpStatusToCount.keySet().iterator();

		while (iterator.hasNext()) {
			FetchStatus fetchStatus = iterator.next();

			mpStatusToCount.put(fetchStatus, 0);
		}

	}

	/**
	 * 记录爬虫爬行每个URL状态的计数器 调用一次计数器加一
	 * 
	 * @param fetchStatus
	 */
	private void count(FetchStatus fetchStatus) {
		logger.debug("count:" + fetchStatus);
		if (null == mpStatusToCount.get(fetchStatus)) {
			// 用一个MAP来记录状态
			mpStatusToCount.put(fetchStatus, 0);
		} else {
			int oldCount = mpStatusToCount.get(fetchStatus);
			mpStatusToCount.put(fetchStatus, oldCount + 1);
		}

	}

	/**
	 * 用来打印当前粒度的定时任务
	 * 
	 * @return
	 */
	private IntervalExecutor getTimerRecord() {
		return new IntervalExecutor() {

			@Override
			public void execute() {
				logger.info("url interval:" + timer.getInterval() + "ms");
			}

		};
	}

	private class AdjustTask extends IntervalExecutor {
		private IAdjusterStrategy strategy;

		public AdjustTask(IAdjusterStrategy strategy) {
			// TODO Auto-generated constructor stub
			this.strategy = strategy;
		}

		@Override
		public void execute() {
			// TODO Auto-generated method stub
			strategy.doAdjust();
			strategy.afterAdjust();
		}

	}

}
